/**
 * 严肃声明：
 * 开源版本请务必保留此注释头信息，若删除我方将保留所有法律责任追究！
 * 本系统已申请软件著作权，受国家版权局知识产权以及国家计算机软件著作权保护！
 * 可正常分享和学习源码，不得用于违法犯罪活动，违者必究！
 * Copyright (c) 2019-2020 十三 all rights reserved.
 * 版权所有，侵权必究！
 */
package ltd.wood.mall.service.impl;

import ltd.wood.mall.common.*;
import ltd.wood.mall.controller.vo.*;
import ltd.wood.mall.dao.WoodMallGoodsMapper;
import ltd.wood.mall.dao.WoodMallOrderItemMapper;
import ltd.wood.mall.dao.WoodMallOrderMapper;
import ltd.wood.mall.dao.WoodMallShoppingCartItemMapper;
import ltd.wood.mall.entity.WoodMallGoods;
import ltd.wood.mall.entity.WoodMallOrder;
import ltd.wood.mall.entity.WoodMallOrderItem;
import ltd.wood.mall.entity.StockNumDTO;
import ltd.wood.mall.service.WoodMallOrderService;
import ltd.wood.mall.util.BeanUtil;
import ltd.wood.mall.util.NumberUtil;
import ltd.wood.mall.util.PageQueryUtil;
import ltd.wood.mall.util.PageResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static java.util.stream.Collectors.groupingBy;

@Service
public class WoodMallOrderServiceImpl implements WoodMallOrderService {

    @Autowired
    private WoodMallOrderMapper woodMallOrderMapper;
    @Autowired
    private WoodMallOrderItemMapper woodMallOrderItemMapper;
    @Autowired
    private WoodMallShoppingCartItemMapper woodMallShoppingCartItemMapper;
    @Autowired
    private WoodMallGoodsMapper woodMallGoodsMapper;

    @Override
    public PageResult getWoodMallOrdersPage(PageQueryUtil pageUtil) {
        List<WoodMallOrder> woodMallOrders = woodMallOrderMapper.findWoodMallOrderList(pageUtil);
        int total = woodMallOrderMapper.getTotalWoodMallOrders(pageUtil);
        PageResult pageResult = new PageResult(woodMallOrders, total, pageUtil.getLimit(), pageUtil.getPage());
        return pageResult;
    }

    @Override
    @Transactional
    public String updateOrderInfo(WoodMallOrder woodMallOrder) {
        WoodMallOrder temp = woodMallOrderMapper.selectByPrimaryKey(woodMallOrder.getOrderId());
        //不为空且orderStatus>=0且状态为出库之前可以修改部分信息
        if (temp != null && temp.getOrderStatus() >= 0 && temp.getOrderStatus() < 3) {
            temp.setTotalPrice(woodMallOrder.getTotalPrice());
            temp.setUserAddress(woodMallOrder.getUserAddress());
            temp.setUpdateTime(new Date());
            if (woodMallOrderMapper.updateByPrimaryKeySelective(temp) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            }
            return ServiceResultEnum.DB_ERROR.getResult();
        }
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    @Override
    @Transactional
    public String checkDone(Long[] ids) {
        //查询所有的订单 判断状态 修改状态和更新时间
        List<WoodMallOrder> orders = woodMallOrderMapper.selectByPrimaryKeys(Arrays.asList(ids));
        String errorOrderNos = "";
        if (!CollectionUtils.isEmpty(orders)) {
            for (WoodMallOrder woodMallOrder : orders) {
                if (woodMallOrder.getIsDeleted() == 1) {
                    errorOrderNos += woodMallOrder.getOrderNo() + " ";
                    continue;
                }
                if (woodMallOrder.getOrderStatus() != 1) {
                    errorOrderNos += woodMallOrder.getOrderNo() + " ";
                }
            }
            if (StringUtils.isEmpty(errorOrderNos)) {
                //订单状态正常 可以执行配货完成操作 修改订单状态和更新时间
                if (woodMallOrderMapper.checkDone(Arrays.asList(ids)) > 0) {
                    return ServiceResultEnum.SUCCESS.getResult();
                } else {
                    return ServiceResultEnum.DB_ERROR.getResult();
                }
            } else {
                //订单此时不可执行出库操作
                if (errorOrderNos.length() > 0 && errorOrderNos.length() < 100) {
                    return errorOrderNos + "订单的状态不是支付成功无法执行出库操作";
                } else {
                    return "你选择了太多状态不是支付成功的订单，无法执行配货完成操作";
                }
            }
        }
        //未查询到数据 返回错误提示
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    @Override
    @Transactional
    public String checkOut(Long[] ids) {
        //查询所有的订单 判断状态 修改状态和更新时间
        List<WoodMallOrder> orders = woodMallOrderMapper.selectByPrimaryKeys(Arrays.asList(ids));
        String errorOrderNos = "";
        if (!CollectionUtils.isEmpty(orders)) {
            for (WoodMallOrder woodMallOrder : orders) {
                if (woodMallOrder.getIsDeleted() == 1) {
                    errorOrderNos += woodMallOrder.getOrderNo() + " ";
                    continue;
                }
                if (woodMallOrder.getOrderStatus() != 1 && woodMallOrder.getOrderStatus() != 2) {
                    errorOrderNos += woodMallOrder.getOrderNo() + " ";
                }
            }
            if (StringUtils.isEmpty(errorOrderNos)) {
                //订单状态正常 可以执行出库操作 修改订单状态和更新时间
                if (woodMallOrderMapper.checkOut(Arrays.asList(ids)) > 0) {
                    return ServiceResultEnum.SUCCESS.getResult();
                } else {
                    return ServiceResultEnum.DB_ERROR.getResult();
                }
            } else {
                //订单此时不可执行出库操作
                if (errorOrderNos.length() > 0 && errorOrderNos.length() < 100) {
                    return errorOrderNos + "订单的状态不是支付成功或配货完成无法执行出库操作";
                } else {
                    return "你选择了太多状态不是支付成功或配货完成的订单，无法执行出库操作";
                }
            }
        }
        //未查询到数据 返回错误提示
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    @Override
    @Transactional
    public String closeOrder(Long[] ids) {
        //查询所有的订单 判断状态 修改状态和更新时间
        List<WoodMallOrder> orders = woodMallOrderMapper.selectByPrimaryKeys(Arrays.asList(ids));
        String errorOrderNos = "";
        if (!CollectionUtils.isEmpty(orders)) {
            for (WoodMallOrder woodMallOrder : orders) {
                // isDeleted=1 一定为已关闭订单
                if (woodMallOrder.getIsDeleted() == 1) {
                    errorOrderNos += woodMallOrder.getOrderNo() + " ";
                    continue;
                }
                //已关闭或者已完成无法关闭订单
                if (woodMallOrder.getOrderStatus() == 4 || woodMallOrder.getOrderStatus() < 0) {
                    errorOrderNos += woodMallOrder.getOrderNo() + " ";
                }
            }
            if (StringUtils.isEmpty(errorOrderNos)) {
                //订单状态正常 可以执行关闭操作 修改订单状态和更新时间
                if (woodMallOrderMapper.closeOrder(Arrays.asList(ids), WoodMallOrderStatusEnum.ORDER_CLOSED_BY_JUDGE.getOrderStatus()) > 0) {
                    return ServiceResultEnum.SUCCESS.getResult();
                } else {
                    return ServiceResultEnum.DB_ERROR.getResult();
                }
            } else {
                //订单此时不可执行关闭操作
                if (errorOrderNos.length() > 0 && errorOrderNos.length() < 100) {
                    return errorOrderNos + "订单不能执行关闭操作";
                } else {
                    return "你选择的订单不能执行关闭操作";
                }
            }
        }
        //未查询到数据 返回错误提示
        return ServiceResultEnum.DATA_NOT_EXIST.getResult();
    }

    @Override
    @Transactional
    public String saveOrder(WoodMallUserVO user, List<WoodMallShoppingCartItemVO> myShoppingCartItems) {
        List<Long> itemIdList = myShoppingCartItems.stream().map(WoodMallShoppingCartItemVO::getCartItemId).collect(Collectors.toList());
        List<Long> goodsIds = myShoppingCartItems.stream().map(WoodMallShoppingCartItemVO::getGoodsId).collect(Collectors.toList());
        List<WoodMallGoods> woodMallGoods = woodMallGoodsMapper.selectByPrimaryKeys(goodsIds);
        //检查是否包含已下架商品
        List<WoodMallGoods> goodsListNotSelling = woodMallGoods.stream()
                .filter(woodMallGoodsTemp -> woodMallGoodsTemp.getGoodsSellStatus() != Constants.SELL_STATUS_UP)
                .collect(Collectors.toList());
        if (!CollectionUtils.isEmpty(goodsListNotSelling)) {
            //goodsListNotSelling 对象非空则表示有下架商品
            WoodMallException.fail(goodsListNotSelling.get(0).getGoodsName() + "已下架，无法生成订单");
        }
        Map<Long, WoodMallGoods> woodMallGoodsMap = woodMallGoods.stream().collect(Collectors.toMap(WoodMallGoods::getGoodsId, Function.identity(), (entity1, entity2) -> entity1));
        //判断商品库存
        for (WoodMallShoppingCartItemVO shoppingCartItemVO : myShoppingCartItems) {
            //查出的商品中不存在购物车中的这条关联商品数据，直接返回错误提醒
            if (!woodMallGoodsMap.containsKey(shoppingCartItemVO.getGoodsId())) {
                WoodMallException.fail(ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult());
            }
            //存在数量大于库存的情况，直接返回错误提醒
            if (shoppingCartItemVO.getGoodsCount() > woodMallGoodsMap.get(shoppingCartItemVO.getGoodsId()).getStockNum()) {
                WoodMallException.fail(ServiceResultEnum.SHOPPING_ITEM_COUNT_ERROR.getResult());
            }
        }
        //删除购物项
        if (!CollectionUtils.isEmpty(itemIdList) && !CollectionUtils.isEmpty(goodsIds) && !CollectionUtils.isEmpty(woodMallGoods)) {
            if (woodMallShoppingCartItemMapper.deleteBatch(itemIdList) > 0) {
                List<StockNumDTO> stockNumDTOS = BeanUtil.copyList(myShoppingCartItems, StockNumDTO.class);
                int updateStockNumResult = woodMallGoodsMapper.updateStockNum(stockNumDTOS);
                if (updateStockNumResult < 1) {
                    WoodMallException.fail(ServiceResultEnum.SHOPPING_ITEM_COUNT_ERROR.getResult());
                }
                //生成订单号
                String orderNo = NumberUtil.genOrderNo();
                int priceTotal = 0;
                //保存订单
                WoodMallOrder woodMallOrder = new WoodMallOrder();
                woodMallOrder.setOrderNo(orderNo);
                woodMallOrder.setUserId(user.getUserId());
                woodMallOrder.setUserAddress(user.getAddress());
                //总价
                for (WoodMallShoppingCartItemVO woodMallShoppingCartItemVO : myShoppingCartItems) {
                    priceTotal += woodMallShoppingCartItemVO.getGoodsCount() * woodMallShoppingCartItemVO.getSellingPrice();
                }
                if (priceTotal < 1) {
                    WoodMallException.fail(ServiceResultEnum.ORDER_PRICE_ERROR.getResult());
                }
                woodMallOrder.setTotalPrice(priceTotal);
                //订单body字段，用来作为生成支付单描述信息，暂时未接入第三方支付接口，故该字段暂时设为空字符串
                String extraInfo = "";
                woodMallOrder.setExtraInfo(extraInfo);
                //生成订单项并保存订单项纪录
                if (woodMallOrderMapper.insertSelective(woodMallOrder) > 0) {
                    //生成所有的订单项快照，并保存至数据库
                    List<WoodMallOrderItem> woodMallOrderItems = new ArrayList<>();
                    for (WoodMallShoppingCartItemVO woodMallShoppingCartItemVO : myShoppingCartItems) {
                        WoodMallOrderItem woodMallOrderItem = new WoodMallOrderItem();
                        //使用BeanUtil工具类将woodMallShoppingCartItemVO中的属性复制到woodMallOrderItem对象中
                        BeanUtil.copyProperties(woodMallShoppingCartItemVO, woodMallOrderItem);
                        //WoodMallOrderMapper文件insert()方法中使用了useGeneratedKeys因此orderId可以获取到
                        woodMallOrderItem.setOrderId(woodMallOrder.getOrderId());
                        woodMallOrderItems.add(woodMallOrderItem);
                    }
                    //保存至数据库
                    if (woodMallOrderItemMapper.insertBatch(woodMallOrderItems) > 0) {
                        //所有操作成功后，将订单号返回，以供Controller方法跳转到订单详情
                        return orderNo;
                    }
                    WoodMallException.fail(ServiceResultEnum.ORDER_PRICE_ERROR.getResult());
                }
                WoodMallException.fail(ServiceResultEnum.DB_ERROR.getResult());
            }
            WoodMallException.fail(ServiceResultEnum.DB_ERROR.getResult());
        }
        WoodMallException.fail(ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult());
        return ServiceResultEnum.SHOPPING_ITEM_ERROR.getResult();
    }

    @Override
    public WoodMallOrderDetailVO getOrderDetailByOrderNo(String orderNo, Long userId) {
        WoodMallOrder woodMallOrder = woodMallOrderMapper.selectByOrderNo(orderNo);
        if (woodMallOrder == null) {
            WoodMallException.fail(ServiceResultEnum.ORDER_NOT_EXIST_ERROR.getResult());
        }
        //验证是否是当前userId下的订单，否则报错
        if (!userId.equals(woodMallOrder.getUserId())) {
            WoodMallException.fail(ServiceResultEnum.NO_PERMISSION_ERROR.getResult());
        }
        List<WoodMallOrderItem> orderItems = woodMallOrderItemMapper.selectByOrderId(woodMallOrder.getOrderId());
        //获取订单项数据
        if (CollectionUtils.isEmpty(orderItems)) {
            WoodMallException.fail(ServiceResultEnum.ORDER_ITEM_NOT_EXIST_ERROR.getResult());
        }
        List<WoodMallOrderItemVO> woodMallOrderItemVOS = BeanUtil.copyList(orderItems, WoodMallOrderItemVO.class);
        WoodMallOrderDetailVO woodMallOrderDetailVO = new WoodMallOrderDetailVO();
        BeanUtil.copyProperties(woodMallOrder, woodMallOrderDetailVO);
        woodMallOrderDetailVO.setOrderStatusString(WoodMallOrderStatusEnum.getWoodMallOrderStatusEnumByStatus(woodMallOrderDetailVO.getOrderStatus()).getName());
        woodMallOrderDetailVO.setPayTypeString(PayTypeEnum.getPayTypeEnumByType(woodMallOrderDetailVO.getPayType()).getName());
        woodMallOrderDetailVO.setWoodMallOrderItemVOS(woodMallOrderItemVOS);
        return woodMallOrderDetailVO;
    }

    @Override
    public WoodMallOrder getWoodMallOrderByOrderNo(String orderNo) {
        return woodMallOrderMapper.selectByOrderNo(orderNo);
    }

    @Override
    public PageResult getMyOrders(PageQueryUtil pageUtil) {
        int total = woodMallOrderMapper.getTotalWoodMallOrders(pageUtil);
        List<WoodMallOrder> woodMallOrders = woodMallOrderMapper.findWoodMallOrderList(pageUtil);
        List<WoodMallOrderListVO> orderListVOS = new ArrayList<>();
        if (total > 0) {
            //数据转换 将实体类转成vo
            orderListVOS = BeanUtil.copyList(woodMallOrders, WoodMallOrderListVO.class);
            //设置订单状态中文显示值
            for (WoodMallOrderListVO woodMallOrderListVO : orderListVOS) {
                woodMallOrderListVO.setOrderStatusString(WoodMallOrderStatusEnum.getWoodMallOrderStatusEnumByStatus(woodMallOrderListVO.getOrderStatus()).getName());
            }
            List<Long> orderIds = woodMallOrders.stream().map(WoodMallOrder::getOrderId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(orderIds)) {
                List<WoodMallOrderItem> orderItems = woodMallOrderItemMapper.selectByOrderIds(orderIds);
                Map<Long, List<WoodMallOrderItem>> itemByOrderIdMap = orderItems.stream().collect(groupingBy(WoodMallOrderItem::getOrderId));
                for (WoodMallOrderListVO woodMallOrderListVO : orderListVOS) {
                    //封装每个订单列表对象的订单项数据
                    if (itemByOrderIdMap.containsKey(woodMallOrderListVO.getOrderId())) {
                        List<WoodMallOrderItem> orderItemListTemp = itemByOrderIdMap.get(woodMallOrderListVO.getOrderId());
                        //将WoodMallOrderItem对象列表转换成WoodMallOrderItemVO对象列表
                        List<WoodMallOrderItemVO> woodMallOrderItemVOS = BeanUtil.copyList(orderItemListTemp, WoodMallOrderItemVO.class);
                        woodMallOrderListVO.setWoodMallOrderItemVOS(woodMallOrderItemVOS);
                    }
                }
            }
        }
        PageResult pageResult = new PageResult(orderListVOS, total, pageUtil.getLimit(), pageUtil.getPage());
        return pageResult;
    }

    @Override
    public String cancelOrder(String orderNo, Long userId) {
        WoodMallOrder woodMallOrder = woodMallOrderMapper.selectByOrderNo(orderNo);
        if (woodMallOrder != null) {
            //验证是否是当前userId下的订单，否则报错
            if (!userId.equals(woodMallOrder.getUserId())) {
                WoodMallException.fail(ServiceResultEnum.NO_PERMISSION_ERROR.getResult());
            }
            //订单状态判断
            if (woodMallOrder.getOrderStatus().intValue() == WoodMallOrderStatusEnum.ORDER_SUCCESS.getOrderStatus()
                    || woodMallOrder.getOrderStatus().intValue() == WoodMallOrderStatusEnum.ORDER_CLOSED_BY_MALLUSER.getOrderStatus()
                    || woodMallOrder.getOrderStatus().intValue() == WoodMallOrderStatusEnum.ORDER_CLOSED_BY_EXPIRED.getOrderStatus()
                    || woodMallOrder.getOrderStatus().intValue() == WoodMallOrderStatusEnum.ORDER_CLOSED_BY_JUDGE.getOrderStatus()) {
                return ServiceResultEnum.ORDER_STATUS_ERROR.getResult();
            }
            if (woodMallOrderMapper.closeOrder(Collections.singletonList(woodMallOrder.getOrderId()), WoodMallOrderStatusEnum.ORDER_CLOSED_BY_MALLUSER.getOrderStatus()) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            } else {
                return ServiceResultEnum.DB_ERROR.getResult();
            }
        }
        return ServiceResultEnum.ORDER_NOT_EXIST_ERROR.getResult();
    }

    @Override
    public String finishOrder(String orderNo, Long userId) {
        WoodMallOrder woodMallOrder = woodMallOrderMapper.selectByOrderNo(orderNo);
        if (woodMallOrder != null) {
            //验证是否是当前userId下的订单，否则报错
            if (!userId.equals(woodMallOrder.getUserId())) {
                return ServiceResultEnum.NO_PERMISSION_ERROR.getResult();
            }
            //订单状态判断 非出库状态下不进行修改操作
            if (woodMallOrder.getOrderStatus().intValue() != WoodMallOrderStatusEnum.ORDER_EXPRESS.getOrderStatus()) {
                return ServiceResultEnum.ORDER_STATUS_ERROR.getResult();
            }
            woodMallOrder.setOrderStatus((byte) WoodMallOrderStatusEnum.ORDER_SUCCESS.getOrderStatus());
            woodMallOrder.setUpdateTime(new Date());
            if (woodMallOrderMapper.updateByPrimaryKeySelective(woodMallOrder) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            } else {
                return ServiceResultEnum.DB_ERROR.getResult();
            }
        }
        return ServiceResultEnum.ORDER_NOT_EXIST_ERROR.getResult();
    }

    @Override
    public String paySuccess(String orderNo, int payType) {
        WoodMallOrder woodMallOrder = woodMallOrderMapper.selectByOrderNo(orderNo);
        if (woodMallOrder != null) {
            //订单状态判断 非待支付状态下不进行修改操作
            if (woodMallOrder.getOrderStatus().intValue() != WoodMallOrderStatusEnum.ORDER_PRE_PAY.getOrderStatus()) {
                return ServiceResultEnum.ORDER_STATUS_ERROR.getResult();
            }
            woodMallOrder.setOrderStatus((byte) WoodMallOrderStatusEnum.ORDER_PAID.getOrderStatus());
            woodMallOrder.setPayType((byte) payType);
            woodMallOrder.setPayStatus((byte) PayStatusEnum.PAY_SUCCESS.getPayStatus());
            woodMallOrder.setPayTime(new Date());
            woodMallOrder.setUpdateTime(new Date());
            if (woodMallOrderMapper.updateByPrimaryKeySelective(woodMallOrder) > 0) {
                return ServiceResultEnum.SUCCESS.getResult();
            } else {
                return ServiceResultEnum.DB_ERROR.getResult();
            }
        }
        return ServiceResultEnum.ORDER_NOT_EXIST_ERROR.getResult();
    }

    @Override
    public List<WoodMallOrderItemVO> getOrderItems(Long id) {
        WoodMallOrder woodMallOrder = woodMallOrderMapper.selectByPrimaryKey(id);
        if (woodMallOrder != null) {
            List<WoodMallOrderItem> orderItems = woodMallOrderItemMapper.selectByOrderId(woodMallOrder.getOrderId());
            //获取订单项数据
            if (!CollectionUtils.isEmpty(orderItems)) {
                List<WoodMallOrderItemVO> woodMallOrderItemVOS = BeanUtil.copyList(orderItems, WoodMallOrderItemVO.class);
                return woodMallOrderItemVOS;
            }
        }
        return null;
    }
}